#include "qmakeproject.h"

#include <QFile>
#include <QFileInfo>
#include <QRegExp>
#include <QDebug>

QMakeProject::QMakeProject( QObject *parent, QString fileName )
	: AbstractProject(parent,fileName)
{
	m_secctions	<< "SOURCES" << "HEADERS" << "TRANSLATIONS" << "FORMS"
			<< "RESOURCES" << "DEFINES";
	loadProject(fileName);
}

QMakeProject::QMakeProject( QString fileName, QObject *parent )
	: AbstractProject(parent,fileName)
{
	m_secctions	<< "SOURCES" << "HEADERS" << "TRANSLATIONS" << "FORMS"
			<< "RESOURCES" << "DEFINES";
	loadProject(fileName);
}

bool QMakeProject::newProject( QString newProjectName )
{
	m_projectName = newProjectName;
	// TODO remove files, subprojects, properties etc
	return true;
}

bool QMakeProject::loadProject( QString newFileName )
{
	if (newFileName.isEmpty())
		return true;

	// based on code from http://doc.trolltech.com/qq/qq01-seriously-weird-qregexp.html
	QFile in( newFileName );
	if ( !in.open(QIODevice::ReadOnly))
		return false;
	QString text = in.readAll();
	m_fileName = in.fileName();
	in.close();
	clear();
	
	text.replace( QRegExp("#[^\n]*"), "" );
	text.replace( QRegExp("\\\\\\s*\n"), " " );
	text.replace( QRegExp("\\s*\n\\s*"), "<END>" );
	
#if 1
	text.replace( QRegExp("="), " = " );
	text.replace( QRegExp("\\+ ="), " += " );
	text.replace( QRegExp("\\- ="), " -= " );
#else
//  	text.replace( QRegExp("(?<![+-])="), " = " );
 	text.replace( QRegExp("[^+-]="), " = " );
	text.replace( QRegExp("+="), " += " );
	text.replace( QRegExp("-="), " -= " );
#endif
	text = text.simplified();
	
	QStringList lines = text.split("<END>");
	foreach( QString line, lines)
	{
		QStringList tokens = line.split(" ");
		if ( tokens.count() < 2)
			continue;
		if (tokens[1] == "=")
			setTokens( tokens );
		else if (tokens[1] == "+=")
			appendTokens( tokens );
		else if (tokens[1] == "-=")
			removeTokens( tokens );
	}

	if (m_data["TARGET"].count()>=1)
		setTargetName(m_data["TARGET"].at(0));
	setProjectName(newFileName);
	m_fileName = newFileName;

	if ((!m_data["TEMPLATE"].empty()) && (m_data["TEMPLATE"][0].toLower() == "subdirs"))
	{	// sweet, using sub projetcs load each one of them
		foreach(QString s, m_data["SUBDIRS"] )
		{
			if (isRelativePath(s))
			{
				QFileInfo fi(m_fileName);
				QString path = fi.path();
				if (path.isEmpty())
					continue;
				s = path + "/" + s;
			}
			QMakeProject *p = new QMakeProject( this, s );
			addSubProject( p );
		}
	}

	return true;
}

bool QMakeProject::saveProject( QString newFileName )
{
	if (newFileName.isEmpty())
		return true;
		
	QFile file( newFileName );
	if ( !file.open(QIODevice::WriteOnly | QIODevice::Text))
		return false;
	
	QTextStream out(&file);
	out << "# file generated by QMakeProject" << "\n\n";
	out << "TARGET = " << getTargetName() << "\n";
	
	QHash<QString,QStringList>::const_iterator i = m_data.constBegin();
	while (i != m_data.constEnd()) 
	{	// the target has been explicity printed before
		if (i.key().toUpper() == "TARGET")
		{
			i++;
			continue;
		}
		
		out << i.key() << " = ";
		for(int j=0; j<i.value().count();j++)
		{
			out << i.value()[j] << " ";
		}
		out << "\n";
		++i;
	}
	m_fileName = file.fileName();
	file.close();

	return true;
}

bool QMakeProject::isLoaded()
{
	return true;
}

void QMakeProject::clear()
{
	AbstractProject::clear();
	m_data.clear();
}


bool QMakeProject::addFile( QString fileName, QString category )
{
	// TODO - way too ugly, needs to be fixed
	if (fileName.startsWith(m_fileName)){
		fileName.remove(0,m_fileName.length());
	}
	
	// we need to guess the category "manually"
	if (category.isEmpty()){
		// normal sources
		if (fileName.endsWith(".cpp",Qt::CaseInsensitive))
			category = "SOURCES";
		else if (fileName.endsWith(".c",Qt::CaseInsensitive))
			category = "SOURCES";
		else if (fileName.endsWith(".cxx",Qt::CaseInsensitive))
			category = "SOURCES";
		else if (fileName.endsWith(".c++",Qt::CaseInsensitive))
			category = "SOURCES";
		else if (fileName.endsWith(".h",Qt::CaseInsensitive))
			category = "HEADERS";
		else if (fileName.endsWith(".hpp",Qt::CaseInsensitive))
			category = "HEADERS";
		
		// Qt files
		else if (fileName.endsWith(".ui",Qt::CaseInsensitive))
			category = "FORMS";
		else if (fileName.endsWith(".qrc",Qt::CaseInsensitive))
			category = "RESOURCES";
		// windows shites
		else if (fileName.endsWith(".rc",Qt::CaseInsensitive))
			category = "RC_FILE";
		else if (fileName.endsWith(".res",Qt::CaseInsensitive))
			category = "RES_FILE";
		
		// flex, bisson, yacc.. whatever
		else if (fileName.endsWith(".yacc",Qt::CaseInsensitive))
			category = "YACCSOURCES";
		else if (fileName.endsWith(".lex",Qt::CaseInsensitive))
			category = "LEXSOURCES";
		else
			category = "UNKNOWN_FILES";
	}
	m_data[category] << fileName;

	return true;
}

bool QMakeProject::removeFile( QString fileName )
{
	 QHashIterator<QString,QStringList> category(m_data);

	 while (category.hasNext())
	 {
		category.next();
		foreach(QString f, category.value())
		{
			if (f != fileName)
				continue;

			// we found filename in category category.key()
			m_data[category.key()].removeOne( fileName );

			// true means we had no problems
			return true;
		}
	 }

	 // the file is not even in the project
	 return false;
 }

QVariant QMakeProject::getVariableValue( QString section )
{
	return m_data[section].join( ", " );
}

void QMakeProject::setVariableValue( QString section, QVariant value )
{
	m_data.remove( section );
	m_data[section] << value.toString();
}

void QMakeProject::addVariableValue( QString section, QVariant value )
{
	m_data[section] << value.toString();
}

void QMakeProject::delVariableValue( QString section, QVariant value )
{
	m_data[section].removeOne( value.toString() );
}

void QMakeProject::delVariable( QString section )
{
	m_data.remove( section );
}

QStringList QMakeProject::getFiles( QString category )
{
	return 	m_data[category];
}

QStringList QMakeProject::getCategoryList()
{
	return m_data.keys();
}

bool QMakeProject::isSectionList(const QString s)
{
	if (s == "SOURCES")
		return true;
	else if (s == "HEADERS")
		return true;
	else if (s == "FORMS")
		return true;
	else if (s == "RESOURCES")
		return true;
	else if (s == "YACCSOURCES")
		return true;
	else if (s == "LEXSOURCES")
		return true;
	// internally used category
	else if (s == "UNKNOWN_FILES")
		return true;
	return false;
}

void QMakeProject::setTokens(QStringList tokens)
{
	QString category = tokens[0];
	m_data[category].clear();
	
	for(int i=2; i<tokens.count();i++)
	{
		m_data[category] << tokens[i];
	}
}

void QMakeProject::appendTokens(QStringList tokens)
{
	QString category = tokens[0];
	
	for(int i=2; i<tokens.count();i++)
	{
		m_data[category] << tokens[i];
	}
}

void QMakeProject::removeTokens(QStringList tokens)
{
	QString category = tokens[0];
	
	for(int i=2; i<tokens.count();i++)
	{
		m_data[category].removeAll(tokens[i]);
	}
}

bool QMakeProject::isRelativePath( QString path )
{
	if (path.isEmpty())
		return true;
	if ((path.at(0) == '/') || (path.at(0) == '\\'))
		return false;
	if (path.length() > 2)
	{
		if (path.at(1) == ':')
		{	//
			QChar drive = path.at(0);
			if (drive.isLetter())
				return false;
		}
		return true;
	}
	else	// it's a drive letter only
		return false;
	
}

// kate: space-indent off; tab-indent on; tab-width 8; indent-width 8;
// kate: show-tabs on; auto-brackets on; end-of-line: unix
// kate: syntax: c++; indent-mode cstyle;auto-insert-doxygen: on;
